package com.ruoyi.common.utils;

import java.lang.management.ManagementFactory;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.temporal.WeekFields;
import java.util.*;

import org.apache.commons.lang3.time.DateFormatUtils;

/**
 * 时间工具类
 *
 * @author ruoyi
 */
public class DateUtils extends org.apache.commons.lang3.time.DateUtils
{
    public static String YYYY = "yyyy";

    public static String YYYY_MM = "yyyy-MM";

	public static String MM = "MM";

	public static String YY_MM = "yy-MM";

    public static String YYYY_MM_DD = "yyyy-MM-dd";

    public static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";

	public final static SimpleDateFormat sdfMonthSimple = new SimpleDateFormat("yyyyMM");

    public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";

    public final static SimpleDateFormat sdfDayCN = new SimpleDateFormat("yyyy年MM月dd日");

	public final static SimpleDateFormat sdfDayCN1 = new SimpleDateFormat("yyyy 年 MM 月 dd 日");

	private final static SimpleDateFormat sdfSimpleTime = new SimpleDateFormat("HH:mm:ss");

	public final static SimpleDateFormat sdfDay = new SimpleDateFormat("yyyy-MM-dd");

    private static final String[] parsePatterns = {
            "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM",
            "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
            "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};

    /**
     * 获取当前Date型日期
     *
     * @return Date() 当前日期
     */
    public static Date getNowDate()
    {
        return new Date();
    }

	/**
	 * 获取yyyyMMddHHmmss格式
	 * @return
	 */
	public static String getMonthStr(Date date) {
		return sdfMonthSimple.format(date);
	}



	/**
	 * 将日期格式 转换成  字符串格式
	 * @param date
	 * @return
	 */
	public static String date2Str(Date date,String format) {
		SimpleDateFormat sdfTimes = new SimpleDateFormat(format);
		return sdfTimes.format(date);
	}


	/**
	 * 获取YYYY-MM-DD HH:mm:ss格式
	 * @return
	 */
	public static String getSimpleTime(Date date) {
		return sdfSimpleTime.format(date);
	}


	/**
	 *  获取多少秒之后的时间
	 * @return
	 */
	public static Date getAfterSecondsByOld(Date date,int seconds){
		Calendar canlendar = Calendar.getInstance(); // java.util包
		canlendar.setTime(date);
		canlendar.add(Calendar.SECOND,seconds);
		return canlendar.getTime();
	}

	/**
     * 获取yyyy年MM月dd日格式
     * @return
     */
    public static String getSdfTimesCN() {
        return sdfDayCN.format(new Date());
    }

	/**
	 * 获取yyyy年MM月dd日格式
	 * @return
	 */
	public static String getSdfTimesCN1(Date date) {
		return sdfDayCN1.format(date);
	}


	/**
	 * 获取YYYY-MM-DD格式
	 * @return
	 */
	public static String getDayByDate(Date date) {
		return sdfDay.format(date);
	}
	/**
	 * 获取本月第一天
	 * @return
	 */
	public static Date getMonthFirstDay(){
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(new Date());
		calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMinimum(Calendar.DAY_OF_MONTH));
		return calendar.getTime();
	}

	public static String getMonthFirstDayStr(){
		return getDayByDate(getMonthFirstDay());
	}


	/**
	 * 获取YYYY-MM-DD格式
	 * @return
	 */
	public static String getDay() {
		return sdfDay.format(new Date());
	}

	/**
	 *  获取当前月份的 最后 、 第一天
	 * @param month
	 * @return
	 */
	public static Date getDayOfMonth(int month, int isLast,int lastDay) {
		Date ret = null;

		//当月一号
		Calendar calendar1 = Calendar.getInstance();
		calendar1.set(Calendar.MONTH, month);
		if(lastDay > 0){
			calendar1.set(Calendar.DAY_OF_MONTH, lastDay);
		}else{
			calendar1.set(Calendar.DAY_OF_MONTH, 1);
		}
		calendar1.set(Calendar.HOUR_OF_DAY,0);
		calendar1.set(Calendar.MINUTE,0);
		calendar1.set(Calendar.SECOND,0);
		calendar1.set(Calendar.MILLISECOND,0);

		if(isLast == 0){
			ret = calendar1.getTime();
		}else{
			//当月最后一天
			Calendar calendar2 = Calendar.getInstance();
			calendar2.set(Calendar.MONTH, month);
			int maxCurrentMonthDay = calendar2.getActualMaximum(Calendar.DAY_OF_MONTH);
			if(lastDay > 0){
				calendar2.set(Calendar.DAY_OF_MONTH, lastDay);
			}else{
				calendar2.set(Calendar.DAY_OF_MONTH, maxCurrentMonthDay);
			}
			calendar2.set(Calendar.HOUR_OF_DAY,23);
			calendar2.set(Calendar.MINUTE,59);
			calendar2.set(Calendar.SECOND,59);
			calendar1.set(Calendar.MILLISECOND,999);
//			System.out.println("本月最后一天: "+sdf.format(calendar2.getTime()));
			ret = calendar2.getTime();
		}
		return ret;
	}

	/**
	 *  获取当前月份的 最后 、 第一天
	 * @param month
	 * @return
	 */
	public static String getDayOfMonthStr(int month, int isLast,int lastDay){
		Date date = getDayOfMonth(month,isLast,lastDay);
		return getDate(date);
	}

	/**
	 * 获取本月最后一天
	 * @return
	 */
	public static Date getMonthLastDay(){
		Calendar calendar2 = Calendar.getInstance();
		calendar2.setTime(new Date());
		calendar2.set(Calendar.DAY_OF_MONTH, calendar2.getActualMaximum(Calendar.DAY_OF_MONTH));
		return calendar2.getTime();
	}

	public static String getMonthLastDayStr(){
		return getDayByDate(getMonthLastDay());
	}


	/**
	 * 以年为单位获取 每个月的 日期范围
	 * @return
	 */
	public static List<Map<String,Object>> getDateTimeByMonth(){
		List<Map<String,Object>> list=  new ArrayList<>();
		for (int i = 0; i < 12; i++){
			Map<String,Object> map = new HashMap<>();
//            SimpleDateFormat sdf = new SimpleDateFormat("MM");
//            String format = sdf.format(new Date());
//            int month = Integer.parseInt(format);
//            System.out.println(month);
			String firstDayOfMonth = getFirstDayOfMonth(i + 1);
//            System.out.println(month+"月第一天："+firstDayOfMonth);
			String lastDayOfMonth = getLastDayOfMonth(i + 1);
//            System.out.println(month+"月的最后一天:"+ lastDayOfMonth);

			map.put("month",i + 1);
			map.put("beginDate",firstDayOfMonth);
			map.put("endDate",lastDayOfMonth);
			list.add(map);
		}
		return list;
	}


	/**
	 * 以年为单位获取 每个月的 日期范围
	 * @return
	 */
	public static List<Map<String,Object>> getDateTimeByMonth(int year){
		List<Map<String,Object>> list=  new ArrayList<>();
		for (int i = 0; i < 12; i++){
			Map<String,Object> map = new HashMap<>();
//            SimpleDateFormat sdf = new SimpleDateFormat("MM");
//            String format = sdf.format(new Date());
//            int month = Integer.parseInt(format);
//            System.out.println(month);
			String firstDayOfMonth = getFirstDayOfMonth(year,i + 1);
//            System.out.println(month+"月第一天："+firstDayOfMonth);
			String lastDayOfMonth = getLastDayOfMonth(year,i + 1);
//            System.out.println(month+"月的最后一天:"+ lastDayOfMonth);

			map.put("month",i + 1);
			map.put("beginDate",firstDayOfMonth);
			map.put("endDate",lastDayOfMonth);
			list.add(map);
		}
		return list;
	}

	/**
	 *  以周为单位  全年的 日期
	 * @return
	 */
	public static List<Map<String,Object>> getDateTimeByWeek(Integer year){
		List<Map<String,Object>> list = new ArrayList<>();
		Calendar calendar= Calendar.getInstance();
		int weekOfYear1 = calendar.get(Calendar.WEEK_OF_YEAR);
		if(year == null){
			year = calendar.get(Calendar.YEAR);
		}
		// java8 根据年份和周数 获取周一和周日日期
		WeekFields weekFields= WeekFields.ISO;
		LocalDate now = LocalDate.now();
		for (int i = 0; i < weekOfYear1;i++){
			Map<String,Object> map = new HashMap<>();
			//输入你想要的年份和周数
			LocalDateTime localDateTime = now.withYear(year).with(weekFields.weekOfYear(),(i)).atStartOfDay();
			System.out.println("localDateTime: " + localDateTime);

//            System.out.println("第"+(i + 1)+"周: ");
			//以周一为每周的第一天

			//周一（第一天）
			LocalDateTime localDate1 = localDateTime.with(weekFields.dayOfWeek(), 1L);
			//周日（第七天）
			LocalDateTime localDate7 = localDateTime.with(weekFields.dayOfWeek(), 7L);

//            System.out.println("周一: " + localDate1.toString() + "   周日: " + localDate7.toString());
//            System.out.println("周日: " + localDate7.toString());

			map.put("week", i);
			map.put("beginDate",localDateToDateStr(localDate1));
			map.put("endDate",localDateToDateStr(localDate7));

			list.add(map);
		}

		return list;
	}


	/**
	 * 获取当前日期, 默认格式为yyyy-MM-dd
	 *
	 * @return String
	 */
	public static String getDate(Date date) {
		return dateTimeNow(date,YYYY_MM_DD);
	}


	public static String dateTimeNow(Date date,final String format) {
		return parseDateToStr(format, date);
	}

	/**
	 *
	 * @return
	 */
	private static String localDateToDateStr(LocalDateTime localDateTime){
		Date date = new Date();
		ZoneId zoneId = ZoneId.systemDefault();
//        LocalDateTime localDateTime = LocalDateTime.now();
		ZonedDateTime zdt = localDateTime.atZone(zoneId);
		date = Date.from(zdt.toInstant());
		return getDate(date);
	}



	/**
	 * 获取当前月第一天
	 * @param month
	 * @return
	 */
	public static String getFirstDayOfMonth(int month) {
		Calendar calendar = Calendar.getInstance();
		// 设置月份
		calendar.set(Calendar.MONTH, month - 1);
		// 获取某月最小天数
		int firstDay = calendar.getActualMinimum(Calendar.DAY_OF_MONTH);
		// 设置日历中月份的最小天数
		calendar.set(Calendar.DAY_OF_MONTH, firstDay);
		// 格式化日期
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		String firstDayDate = sdf.format(calendar.getTime());//+" 00:00:00";
		return firstDayDate;
	}



	/**
	 * 获取当前月第一天
	 * @param year
	 * @param month
	 * @return
	 */
	public static String getFirstDayOfMonth(int year, int month) {
		Calendar calendar = Calendar.getInstance();
		// 设置月份
		calendar.set(Calendar.YEAR,year);
		// 设置月份
		calendar.set(Calendar.MONTH, month - 1);
		// 获取某月最小天数
		int firstDay = calendar.getActualMinimum(Calendar.DAY_OF_MONTH);
		// 设置日历中月份的最小天数
		calendar.set(Calendar.DAY_OF_MONTH, firstDay);
		// 格式化日期
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		String firstDayDate = sdf.format(calendar.getTime());//+" 00:00:00";
		return firstDayDate;
	}

	/**
	 * 获取当前月最后一天
	 * @param month
	 * @return
	 */
	public static String getLastDayOfMonth(int month) {
		Calendar calendar = Calendar.getInstance();
		// 设置月份
		calendar.set(Calendar.MONTH, month - 1);
		// 获取某月最大天数
		int lastDay = 0;
		//2月的平年瑞年天数
		if(month==2) {
			// 这个api在计算2020年2月的过程中有问题
			lastDay = calendar.getLeastMaximum(Calendar.DAY_OF_MONTH);
		}else {
			lastDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
		}
		// 设置日历中月份的最大天数
		calendar.set(Calendar.DAY_OF_MONTH, lastDay);
		// 格式化日期
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		String lastDayDate = sdf.format(calendar.getTime());//+" 23:59:59";
		return lastDayDate;
	}


	/**
	 * 获取当前月最后一天
	 * @param month
	 * @return
	 */
	public static String getLastDayOfMonth(int year, int month) {
		Calendar calendar = Calendar.getInstance();
		// 设置月份
		calendar.set(Calendar.YEAR,year);
		// 设置月份
		calendar.set(Calendar.MONTH, month - 1);
		// 获取某月最大天数
		int lastDay = 0;
		//2月的平年瑞年天数
		if(month==2) {
			// 这个api在计算2020年2月的过程中有问题
			lastDay = calendar.getLeastMaximum(Calendar.DAY_OF_MONTH);
		}else {
			lastDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
		}
		// 设置日历中月份的最大天数
		calendar.set(Calendar.DAY_OF_MONTH, lastDay);
		// 格式化日期
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		String lastDayDate = sdf.format(calendar.getTime());//+" 23:59:59";
		return lastDayDate;
	}

	/**
	 *  获取前几个月或者后几个月
	 * @param month  前几个月 用负数   后几个月 用正数
	 * @return
	 */
	public static Map<String,Object> getMonthBy(int month){
		Map<String,Object> map = new HashMap<>();
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM");
		Date date = new Date();
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.add(Calendar.MONTH, month); //设置为前3月
		date = calendar.getTime();
		int yearNum = date.getYear();
		int montNum = date.getMonth();
		String defaultStartDate = simpleDateFormat.format(date); //格式化前month月的时间
		map.put("month_num",montNum);
		map.put("beginTime",defaultStartDate + "-01 00:00:00");
		map.put("endTime",getLastDayOfMonth(yearNum,montNum+1) + " 23:59:59");
		return map;
	}

	/**
     * 获取当前日期, 默认格式为yyyy-MM-dd
     *
     * @return String
     */
    public static String getDate()
    {
        return dateTimeNow(YYYY_MM_DD);
    }

	public static String getYearMonthTime(Date date)
	{
		return dateTimeNow(YYYY_MM,date);
	}

	public static String getMonthTime(Date date)
	{
		return dateTimeNow(MM,date);
	}
	public static String getYeaTime(Date date)
	{
		return dateTimeNow(YYYY,date);
	}
	public static String getYear()
	{
		return dateTimeNow(YYYY);
	}

	public static String getSimpleYearMonthTime(Date date)
	{
		return dateTimeNow(YY_MM,date);
	}

    public static String getTime()
    {
        return dateTimeNow(YYYY_MM_DD_HH_MM_SS);
    }

	public static String getTime(Date date)
	{
		return dateTimeNow(YYYY_MM_DD_HH_MM_SS,date);
	}

    public static String dateTimeNow()
    {
        return dateTimeNow(YYYYMMDDHHMMSS);
    }

	public static String dateTimeNow(final String format,Date date)
	{
		return parseDateToStr(format, date);
	}
    public static String dateTimeNow(final String format)
    {
        return parseDateToStr(format, new Date());
    }

    public static String dateTime(final Date date)
    {
        return parseDateToStr(YYYY_MM_DD, date);
    }

    public static String parseDateToStr(final String format, final Date date) {
        return new SimpleDateFormat(format).format(date);
    }

    public static Date dateTime(final String format, final String ts) {
        try {
            return new SimpleDateFormat(format).parse(ts);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }



	public static String getLastMonth(){
		// 获取当前日期
		Calendar calendar = Calendar.getInstance();

		// 设置为前一个月
		calendar.add(Calendar.MONTH, -1);

		// 获取前一个月的日期
		Date previousMonthDate = calendar.getTime();

//		// 格式化日期输出
//		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
//		String formattedDate = sdf.format(previousMonthDate);
//
//		// 输出结果
//		System.out.println("前一个月的日期: " + formattedDate);
		return getMonthTime(previousMonthDate);
	}

    /**
     * 日期路径 即年/月/日 如2018/08/08
     */
    public static String datePath() {
        Date now = new Date();
        return DateFormatUtils.format(now, "yyyy/MM/dd");
    }

    /**
     * 日期路径 即年/月/日 如20180808
     */
    public static String dateTime() {
        Date now = new Date();
        return DateFormatUtils.format(now, "yyyyMMdd");
    }



    public  static Date getDateTimeByDayCountBefore(int days){
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(new Date());
		calendar.add(Calendar.DAY_OF_MONTH,days);
		calendar.set(Calendar.HOUR_OF_DAY,0);
		calendar.set(Calendar.MINUTE,0);
		calendar.set(Calendar.SECOND,0);
		Date dateTime = calendar.getTime();
		return dateTime;
	}


	public  static Date getTodayDateTimeZero(){
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(new Date());
		calendar.set(Calendar.HOUR_OF_DAY,0);
		calendar.set(Calendar.MINUTE,0);
		calendar.set(Calendar.SECOND,0);
		Date dateTime = calendar.getTime();
		return dateTime;
	}


	public static void main(String[] args) {
//		Date date = getDateTimeByDayCountBefore(-7);


		Map<String,Object> map = getMonthBy(0);

		System.out.println("1个月之前时间： " + map);


//		System.out.println("7天之前时间： " + getTime(date));
	}


    /**
     * 日期型字符串转化为日期 格式
     */
    public static Date parseDate(Object str) {
        if (str == null) {
            return null;
        }
        try {
            return parseDate(str.toString(), parsePatterns);
        } catch (ParseException e) {
            return null;
        }
    }

    /**
     * 获取服务器启动时间
     */
    public static Date getServerStartDate() {
        long time = ManagementFactory.getRuntimeMXBean().getStartTime();
        return new Date(time);
    }

    /**
     * 计算两个时间差
     */
    public static String getDatePoor(Date endDate, Date nowDate) {
        long nd = 1000 * 24 * 60 * 60;
        long nh = 1000 * 60 * 60;
        long nm = 1000 * 60;
        // long ns = 1000;
        // 获得两个时间的毫秒时间差异
        long diff = endDate.getTime() - nowDate.getTime();
        // 计算差多少天
        long day = diff / nd;
        // 计算差多少小时
        long hour = diff % nd / nh;
        // 计算差多少分钟
        long min = diff % nd % nh / nm;
        // 计算差多少秒//输出结果
        // long sec = diff % nd % nh % nm / ns;
        return day + "天" + hour + "小时" + min + "分钟";
    }
}
